﻿using System;
using System.Collections.Generic;
using System.Text;
using HostTool.Util;
using System.Threading;

namespace HostTool.Protocol
{


  public  delegate void RequestCallbackHandler(Frame frame);


    /// <summary>
    /// 查询数据包
    /// </summary>
   public class RequestPackage
    {

       byte[] data;
       int dataLength = 0; //要发送的数据长度
       byte[] txBuffer;

       AutoResetEvent WaitEvent = new AutoResetEvent(false);

       Frame resposeFrame = null;

        /// <summary>
        /// 命令
        /// </summary>
       public byte Cmd
       {
           get;
           private set;
       }
        /// <summary>
        /// 业务类型
        /// </summary>
       public byte Transaction
       {
           get;
           private set;
       }

       public byte DstPort
       {
           get;
           private set;
       }


       public byte[] TxBuffer
       {
           get
           {
             
               CalculateFrame();
               //计算要发送的参数
               return txBuffer;
           }
       }

       public int TxLength
       {
           get;
           private set;
       }


       public void Reset()
       {
           resposeFrame = null; //fixed me:可以在其他地方设置 
           WaitEvent.Reset();
       }

       public int FilterTransaction
       {
           get;
           set;
       }

       public int FilterCmd
       {
           get;
           set;
       }


       public int WaitTime
       {
           get;
           private set;
       }

        public RequestPackage(byte dstPort,byte transaction,byte cmd,byte[] data,int dataLength,byte[] txBuffer,int waitTime)
        {
            this.DstPort = dstPort;
            this.Transaction = transaction;
            this.Cmd = cmd;
            this.data = data;
            this.dataLength = dataLength;
            this.txBuffer = txBuffer;


            this.FilterTransaction = -1;
            this.FilterCmd = -1;

            this.WaitTime = waitTime;
        }

        public Frame WaitResponse()
        {
            return WaitResponse(5000);
        }
        public Frame WaitResponse(int timeout)
        {
            if (timeout == 0) return resposeFrame;

            if (timeout > 0)
            {
                WaitEvent.WaitOne(timeout, false);
            }
            else
            {
                WaitEvent.WaitOne();
            }
            return resposeFrame;

        }

        public void NotifyFrame(Frame frame)
        {
            resposeFrame = frame;
            WaitEvent.Set();
        }


        void CalculateFrame()
        {
            int dataLen = dataLength + 6 + 2; 


            //计算CRC
            txBuffer[0] = (byte)((dataLen >> 8) & 0xff);
            txBuffer[1] = (byte)(dataLen & 0xff);

            txBuffer[2] = 0x00;//源端口 (综合测试仪)
            if ((Transaction == 0x0a) && (Cmd == 0xaa))
            {
                txBuffer[2] = 0x80; //flash 的解锁 上锁 必须为0x80 真是垃圾协议FUCK
            }
            txBuffer[3] = 0;
            txBuffer[4] = DstPort; //目的端口
            txBuffer[5] = 0;
            txBuffer[6] = Transaction; //业务
            txBuffer[7] = Cmd; //命令

            for (int i = 0; i < dataLength; i++)
            {
                txBuffer[i + 8] = data[i];
            }

            UInt16 crc = CRC16.ComputeCRC16(txBuffer, 0, dataLen);

            int index = 0;

            //帧头
            txBuffer[index] = 0x10;
            index++;
            txBuffer[index] = 0x02;
            index++;


            //数据长度
            txBuffer[index] = (byte)((dataLen >> 8) & 0xff);
            index++;
            if (txBuffer[index - 1] == 0x10)
            {
                txBuffer[index] = 0x10;
                index++;
            }
            txBuffer[index] = (byte)(dataLen & 0xff);
            index++;
            if (txBuffer[index - 1] == 0x10)
            {
                txBuffer[index] = 0x10;
                index++;
            }
            //源端口
            txBuffer[index] = 0x00;
            if ((Transaction == 0x0a) && (Cmd == 0xaa))
            {
                txBuffer[index] = 0x80; //flash 的解锁 上锁 必须为0x80 真是垃圾协议FUCK
            }
            index++;
            //源端口长度
            txBuffer[index] = 0;
            index++;
            //目的端口
            txBuffer[index] = DstPort;
            index++;
            if (txBuffer[index - 1] == 0x10)
            {
                txBuffer[index] = 0x10;
                index++;
            }
            //目的地址长度
            txBuffer[index] = 0;
            index++;
            //业务
            txBuffer[index] = Transaction;
            index++;
            if (txBuffer[index - 1] == 0x10)
            {
                txBuffer[index] = 0x10;
                index++;
            }
            //命令
            txBuffer[index] = Cmd;
            index++;
            if (txBuffer[index - 1] == 0x10)
            {
                txBuffer[index] = 0x10;
                index++;
            }

            //数据
            for (int i = 0; i < dataLength; i++)
            {
                txBuffer[index] = data[i];
                index++;
                if (txBuffer[index - 1] == 0x10)
                {
                    txBuffer[index] = 0x10;
                    index++;
                }
            }
            //CRC
            txBuffer[index] = (byte)((crc >> 8) & 0xff);
            index++;
            if (txBuffer[index - 1] == 0x10)
            {
                txBuffer[index] = 0x10;
                index++;
            }
            txBuffer[index] = (byte)(crc & 0xff);
            index++;
            if (txBuffer[index - 1] == 0x10)
            {
                txBuffer[index] = 0x10;
                index++;
            }
            //帧尾
            txBuffer[index] = 0x10;
            index++;
            txBuffer[index] = 0x03;
            index++;


            TxLength = index;

    
        }



        public RequestCallbackHandler CallbackHandler;

    }
}
